void start_of_day(void);
/* Command line options and variables. */
-unsigned long opt_dom0_ip = 0;
unsigned int opt_ser_baud = 9600; /* default baud for COM1 */
unsigned int opt_dom0_mem = 16000; /* default kbytes for DOM0 */
unsigned int opt_ne_base = 0; /* NE2k NICs cannot be probed */
void *var;
} opts[] = {
{ "ser_baud", OPT_UINT, &opt_ser_baud },
- { "dom0_ip", OPT_IP, &opt_dom0_ip },
{ "dom0_mem", OPT_UINT, &opt_dom0_mem },
{ "ne_base", OPT_UINT, &opt_ne_base },
{ "ifname", OPT_STR, &opt_ifname },
dom0_params.num_vifs = 1;
dom0_params.memory_kb = opt_dom0_mem;
- if ( opt_dom0_ip == 0 )
- panic("Must specify an IP address for domain 0!\n");
-
- add_default_net_rule(0, opt_dom0_ip); // add vfr info for dom0
-
new_dom = do_newdomain(0, 0);
if ( new_dom == NULL ) panic("Error creating domain 0\n");
iph->id = 0xdead;
iph->ttl = 255;
iph->protocol= 17;
- iph->daddr = htonl(opt_dom0_ip);
- iph->saddr = htonl(0xa9fe0001);
+ iph->daddr = htonl(0xa9fe0001); /* 169.254.0.1 */
+ iph->saddr = htonl(0xa9fe0001); /* 169.254.0.1 */
iph->tot_len = htons(hdr_size + len);
iph->check = 0;
iph->check = compute_cksum((__u16 *)iph, sizeof(struct my_iphdr)/2);
return 0;
}
-/* add_default_net_rule - Set up default network path (ie for dom0).
- *
- * this is a utility function to route all traffic with the specified
- * ip address to the specified vif. It's used to set up domain zero.
- */
-
-void add_default_net_rule(unsigned long vif_id, u32 ipaddr)
-{
- net_rule_t new_rule;
-
- //outbound rule.
- memset(&new_rule, 0, sizeof(net_rule_t));
- new_rule.src_addr = ipaddr;
- new_rule.src_addr_mask = 0xffffffff;
- new_rule.src_vif = vif_id;
- new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
- new_rule.action = NETWORK_ACTION_ACCEPT;
- new_rule.proto = NETWORK_PROTO_ANY;
- add_net_rule(&new_rule);
-
- //inbound rule;
- memset(&new_rule, 0, sizeof(net_rule_t));
- new_rule.dst_addr = ipaddr;
- new_rule.dst_addr_mask = 0xffffffff;
- new_rule.src_vif = VIF_ANY_INTERFACE;
- new_rule.dst_vif = vif_id;
- new_rule.action = NETWORK_ACTION_ACCEPT;
- new_rule.proto = NETWORK_PROTO_ANY;
- add_net_rule(&new_rule);
-
-}
-
/* print_net_rule - Print a single net rule.
*/
if ( ((ent->r.src_vif == src_vif)
|| (ent->r.src_vif == VIF_ANY_INTERFACE)) &&
+ (src_vif != ent->r.dst_vif) &&
+
(!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask )) &&
(!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask )) &&
(!((ent->r.src_port ^ src_port) & ent->r.src_port_mask )) &&
case NETWORK_OP_GETRULELIST:
{
- // This should eventually ship a rule list up to the VM
- // to be printed in its procfs. For now, we just print the rules.
-
+ /*
+ * This should ship a rule list up to the guest OS. For now
+ * we just dump the rules to our own console.
+ */
print_net_rule_list();
}
break;
void __init net_init (void)
{
+ net_rule_t new_rule;
+
net_rule_list = NULL;
- net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
- net_rule_cache = kmem_cache_create("net_rule_cache", sizeof(net_rule_ent_t),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ net_vif_cache = kmem_cache_create("net_vif_cache",
+ sizeof(net_vif_t),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ net_rule_cache = kmem_cache_create("net_rule_cache",
+ sizeof(net_rule_ent_t),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ /* Bootstrap outbound rule. */
+ memset(&new_rule, 0, sizeof(net_rule_t));
+ new_rule.src_vif = 0;
+ new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+ new_rule.action = NETWORK_ACTION_ACCEPT;
+ new_rule.proto = NETWORK_PROTO_ANY;
+ add_net_rule(&new_rule);
+
+ /* Bootstrap inbound rule. */
+ memset(&new_rule, 0, sizeof(net_rule_t));
+ new_rule.src_vif = VIF_ANY_INTERFACE;
+ new_rule.dst_vif = 0;
+ new_rule.action = NETWORK_ACTION_ACCEPT;
+ new_rule.proto = NETWORK_PROTO_ANY;
+ add_net_rule(&new_rule);
}
net_vif_t *create_net_vif(int domain);
void destroy_net_vif(net_vif_t *vif);
void unlink_net_vif(net_vif_t *vif);
-void add_default_net_rule(unsigned long vif_id, u32 ipaddr);
net_vif_t *net_get_target_vif(u8 *data, unsigned int len, net_vif_t *src_vif);
net_vif_t *find_vif_by_id(unsigned long id);
net_ring_t *net_ring;
net_idx_t *net_idx;
spinlock_t tx_lock;
+ unsigned int idx; /* Domain-specific index of this VIF. */
/*
* {tx,rx}_skbs store outstanding skbuffs. The first entry in each
}
+/*
+ * This notifier is installed for domain 0 only.
+ * All other domains have VFR rules installed on their behalf by domain 0
+ * when they are created. For bootstrap, Xen creates wildcard rules for
+ * domain 0 -- this notifier is used to detect when we find our proper
+ * IP address, so we can poke down proper rules and remove the wildcards.
+ */
+static int inetdev_notify(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+ struct net_device *dev = ifa->ifa_dev->dev;
+ struct list_head *ent;
+ struct net_private *np;
+ int idx = -1;
+ network_op_t op;
+ static int removed_bootstrap_rules = 0;
+
+ list_for_each ( ent, &dev_list )
+ {
+ np = list_entry(dev_list.next, struct net_private, list);
+ if ( np->dev == dev )
+ idx = np->idx;
+ }
+
+ if ( idx == -1 )
+ goto out;
+
+ memset(&op, 0, sizeof(op));
+ op.u.net_rule.proto = NETWORK_PROTO_ANY;
+ op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
+
+ if ( event == NETDEV_UP )
+ op.cmd = NETWORK_OP_ADDRULE;
+ else if ( event == NETDEV_DOWN )
+ op.cmd = NETWORK_OP_DELETERULE;
+ else
+ goto out;
+
+ op.u.net_rule.src_vif = idx;
+ op.u.net_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+ op.u.net_rule.src_addr = ntohl(ifa->ifa_address);
+ op.u.net_rule.src_addr_mask = ~0UL;
+ op.u.net_rule.dst_addr = 0;
+ op.u.net_rule.dst_addr_mask = 0;
+ (void)HYPERVISOR_network_op(&op);
+
+ op.u.net_rule.src_vif = VIF_ANY_INTERFACE;
+ op.u.net_rule.dst_vif = idx;
+ op.u.net_rule.src_addr = 0;
+ op.u.net_rule.src_addr_mask = 0;
+ op.u.net_rule.dst_addr = ntohl(ifa->ifa_address);
+ op.u.net_rule.dst_addr_mask = ~0UL;
+ (void)HYPERVISOR_network_op(&op);
+
+ /*
+ * Xen creates a pair of bootstrap rules which allows domain 0 to
+ * send and receive any packet. These rules can be removed once we
+ * have configured an IP address.
+ */
+ if ( (idx == 0) && (event == NETDEV_UP) && !removed_bootstrap_rules )
+ {
+ memset(&op, 0, sizeof(op));
+ op.cmd = NETWORK_OP_DELETERULE;
+ op.u.net_rule.proto = NETWORK_PROTO_ANY;
+ op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
+
+ op.u.net_rule.src_vif = 0;
+ op.u.net_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+ (void)HYPERVISOR_network_op(&op);
+
+ op.u.net_rule.src_vif = VIF_ANY_INTERFACE;
+ op.u.net_rule.dst_vif = 0;
+ (void)HYPERVISOR_network_op(&op);
+
+ removed_bootstrap_rules = 1;
+ }
+
+ out:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block notifier_inetdev = {
+ .notifier_call = inetdev_notify,
+ .next = NULL,
+ .priority = 0
+};
+
+
int __init init_module(void)
{
int i, fixmap_idx=-1, err;
INIT_LIST_HEAD(&dev_list);
+ /*
+ * Domain 0 must poke its own network rules as it discovers its IP
+ * addresses. All other domains have a privileged "parent" to do this
+ * for them at start of day.
+ */
+ if ( start_info.dom_id == 0 )
+ (void)register_inetaddr_notifier(¬ifier_inetdev);
+
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
{
if ( start_info.net_rings[i] == 0 )
np = dev->priv;
np->net_ring = (net_ring_t *)fix_to_virt(FIX_NETRING0_BASE+fixmap_idx);
np->net_idx = &HYPERVISOR_shared_info->net_idx[i];
+ np->idx = i;
SET_MODULE_OWNER(dev);
dev->open = network_open;
unregister_netdev(dev);
kfree(dev);
}
+
+ if ( start_info.dom_id == 0 )
+ (void)unregister_inetaddr_notifier(¬ifier_inetdev);
}